package com.yungu.swift.order.service.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.github.miemiedev.mybatis.paginator.domain.PageBounds;
import com.github.miemiedev.mybatis.paginator.domain.PageList;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.yungu.swift.assets.driver.model.dto.CarModelValuationDto;
import com.yungu.swift.assets.driver.model.dto.DriverDto;
import com.yungu.swift.assets.driver.model.dto.DriverStatusCycleDto;
import com.yungu.swift.assets.driver.service.CarModelValuationService;
import com.yungu.swift.assets.driver.service.DriverService;
import com.yungu.swift.assets.passenger.model.dto.PassengerDto;
import com.yungu.swift.assets.passenger.service.PassengerService;
import com.yungu.swift.autoconfig.redis.RedisCacheService;
import com.yungu.swift.base.ResponseData;
import com.yungu.swift.base.model.PageVo;
import com.yungu.swift.base.model.admin.AdminParam;
import com.yungu.swift.constants.CommonConstant;
import com.yungu.swift.constants.OrderConstant;
import com.yungu.swift.lbs.model.Coordinate;
import com.yungu.swift.lbs.model.DriverLocation;
import com.yungu.swift.lbs.model.vo.OrderLocationVo;
import com.yungu.swift.lbs.service.LocationService;
import com.yungu.swift.order.dao.OrderDetailMapper;
import com.yungu.swift.order.dao.OrderMapper;
import com.yungu.swift.order.dao.OrderOperateLogMapper;
import com.yungu.swift.order.helper.PassengerHelper;
import com.yungu.swift.order.model.dto.OrderDetailDto;
import com.yungu.swift.order.model.dto.OrderDto;
import com.yungu.swift.order.model.dto.OrderFareDto;
import com.yungu.swift.order.model.dto.OrderOperateLogDto;
import com.yungu.swift.order.model.param.*;
import com.yungu.swift.order.model.vo.*;
import com.yungu.swift.order.processor.CrosstownOrderProcessor;
import com.yungu.swift.order.service.*;
import com.yungu.swift.order.thread.inform.InformThreadPoolUtil;
import com.yungu.swift.order.thread.inform.OrderEvent;
import com.yungu.swift.order.thread.inform.OrderStatusInformThread;
import com.yungu.swift.socket.push.model.PushContent;
import com.yungu.swift.socket.push.service.PushService;
import com.yungu.swift.system.sys.model.dto.SysAssignConfigDto;
import com.yungu.swift.system.sys.model.param.AdminAssetsPageAdmin;
import com.yungu.swift.system.sys.service.SysAssignConfigService;
import com.yungu.swift.system.sys.service.SysCityService;
import com.yungu.swift.system.sys.service.SysDepartLimitService;
import com.yungu.swift.system.sys.service.SysWayService;
import com.yungu.swift.utils.MapUtils;
import com.yungu.swift.utils.ParamUtil;
import com.yungu.swift.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

import static com.yungu.swift.order.helper.OrderHelper.*;

/**
 * Created by Zerrion on 2017/10/13.
 */
@Slf4j
@Service
public class OrderAdminServiceImpl implements OrderAdminService {

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private OrderOperateLogMapper orderOperateLogMapper;
    @Autowired
    private OrderService orderService;
    @Autowired
    private OrderTrackMileageService orderTrackMileageService;
    @Autowired
    private OrderSecretNoService orderSecretNoService;
    @Autowired
    private RedisCacheService redisCacheService;
    @Autowired
    private CrosstownOrderProcessor crosstownOrderProcessor;
    @Autowired
    private RefundService refundService;
    @Reference
    private PassengerService passengerService;
    @Reference
    private DriverService driverService;
    @Reference
    private SysCityService sysCityService;
    @Reference
    private SysWayService sysWayService;
    @Reference
    private CarModelValuationService carModelValuationService;
    @Reference
    private OrderAssignService orderAssignService;
    @Reference
    private OrderRiskControlService orderRiskControlService;
    @Reference
    private PushService pushService;
    @Reference
    private SysAssignConfigService sysAssignConfigService;
    @Reference
    private SysDepartLimitService sysDepartLimitService;
    @Reference
    private LocationService locationService;

    /**
     * 异常备注订单退款类型
     * 2.费用不认可-司机绕路 8.费用不认可-司机多收费 9.费用不认可-司机额外收费 10.异常订单-乘客未上车扣费 11.异常订单-司机刷单
     */
    private static final Set<Integer> ABNORMAL_LIST = Sets.newHashSet(2, 8, 9, 10, 11);

    @Override
    public ResponseData<Boolean> createOrder(AdminOrderParam orderParam) {
        PassengerDto passengerDto = passengerService.get(MapUtils.build("mobile", orderParam.getPassengerMobile())).getData();
        if (passengerDto == null) {
            passengerDto = PassengerHelper.newPassenger(orderParam.getPassengerMobile(), orderParam.getPassengerName(), orderParam.getAppid());
        }
        // 判断能否下单
        ResponseData<Boolean> result = orderRiskControlService.canPasCreateOrder(passengerDto.getUuid(),
                orderParam.getAppid(), null, orderParam.getPassengerMobile(), orderParam.getTypeTime());
        if (!result.isSuccess()) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "不符合下单条件");
        }
        //判断预约时间的正确性
        if (CommonConstant.TYPE_TIME_APPIONT == orderParam.getTypeTime() && orderParam.getDepartTime() != null) {
            if (orderParam.getDepartTime().before(new Date())) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "预约时间不能小于当前时间");
            }
        }
        //保存订单主表order
        OrderDto orderDto = new OrderDto();
        orderDto.setUuid(StringUtils.buildUUID());
        orderDto.setPassengerUuid(passengerDto.getUuid());
        //订单类型（时效性）：1 实时订单， 2 预约订单 5 接机订单
        orderDto.setTypeTime(orderParam.getTypeTime());
        //订单类型（行程）：1 出租车；2 专车； 3 拼车
        orderDto.setTypeTrip(orderParam.getTypeTrip());
        //订单类型（个人/企业）：1 个人；2 企业
        orderDto.setTypeEnt(OrderConstant.ORDER_TYPE_ENT_PER);
        //订单类型（本人/代客）：1 本人；2 代客
        orderDto.setTypeSelf(OrderConstant.ORDER_TYPE_SELF_ME);
        //订单类型（主/子订单）：1 主订单；2 子订单
        orderDto.setTypeMain(OrderConstant.ORDER_TYPE_MAIN);
        //订单来源：1 APP移动端；2 微信公众号；3 电话叫车；4 pc网站 5:后台下单
        orderDto.setSource(OrderConstant.ORDER_SOURCE_ADMIN);
        orderDto.setMainStatus(OrderConstant.ORDER_MAIN_STATUS_INITIAL);
        orderDto.setSubStatus(OrderConstant.ORDER_STATUS_WAIT);
        //预支付方式（1企业支付，2个人支付）
        orderDto.setPrepayType(OrderConstant.PREPAY_TYPE_OWN);
        orderDto.setAppid(orderParam.getAppid());
        orderDto.setPassengerLng(orderParam.getPassengerLng());
        orderDto.setPassengerLat(orderParam.getPassengerLat());
        orderDto.setSeatNum(orderParam.getSeatNum());
        orderDto.setMatchTime(new Date());
        //保存订单详情表order_detail
        OrderDetailDto orderDetailDto = new OrderDetailDto();
        orderDetailDto.setAppid(orderParam.getAppid());
        //仅保存接口传来的数据，若未传则为空
        orderDetailDto.setActualPasNam(ParamUtil.defaultIfNull(orderParam.getPassengerName(), passengerDto.getNickname()));
        orderDetailDto.setActualPasMob(ParamUtil.defaultIfNull(orderParam.getPassengerMobile(), passengerDto.getMobile()));
        //预约单唯一不同的字段
        orderDetailDto.setDeparTime(ParamUtil.defaultIfNull(orderParam.getDepartTime(), new Date()));
        orderDetailDto.setPlanTrip(orderParam.getPlanTrip());
        orderDetailDto.setPlanTripFare(BigDecimal.valueOf(orderParam.getPlanTripFare()));
        orderDetailDto.setPlanCouponFare(BigDecimal.valueOf(orderParam.getPlanCouponFare()));
        orderDetailDto.setPlanTrip(orderParam.getPlanTrip());
        orderDetailDto.setPlanFare(orderParam.getPlanFare());
        orderDetailDto.setOriginAddress(orderParam.getOriginAddress());
        orderDetailDto.setOriginDetailAddress(orderParam.getOriginAddressDetail());
        orderDetailDto.setOriginCity(orderParam.getOriginCity());
        orderDetailDto.setOriginLng(orderParam.getOriginLng());
        orderDetailDto.setOriginLat(orderParam.getOriginLat());
        orderDetailDto.setOriginCityUuid(sysCityService.getCityUuidByName(orderParam.getOriginCity()).getData());
        orderDetailDto.setDestAddress(orderParam.getDestAddress());
        orderDetailDto.setDestDetailAddress(orderParam.getDestAddressDetail());
        orderDetailDto.setDestCity(orderParam.getDestCity());
        orderDetailDto.setDestLng(orderParam.getDestLng());
        orderDetailDto.setDestLat(orderParam.getDestLat());
        orderDetailDto.setDestCityUuid(sysCityService.getCityUuidByName(orderParam.getDestCity()).getData());
        orderDetailDto.setRemark(orderParam.getRemark());
        orderDetailDto.setOriginAreaCode(orderParam.getOriginAreaCode());
        orderDetailDto.setPlanDuration(orderParam.getPlanDuration());
        //保存订单价格表
        OrderFareDto orderFareDto = new OrderFareDto();
        orderFareDto.setCarModelValuationUuid(orderParam.getFareRuleUuid());
        orderFareDto.setCreateOn(new Date());
        //出租车逻辑
        if (CommonConstant.BUSINESS_TYPE_TAXI == orderParam.getTypeModule()) {
            Map<String, Object> paramMap = MapUtils.build(5);
            paramMap.put("appid", orderParam.getAppid());
            paramMap.put("city", orderParam.getOriginCity());
            //出租车
            paramMap.put("businessType", CommonConstant.BUSINESS_TYPE_TAXI);
            //预约或实时
            paramMap.put("orderTypeTime", orderParam.getTypeTime());
            CarModelValuationDto carValuationDto = carModelValuationService.getCarModel(paramMap).getData();
            if (carValuationDto == null) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "未找到对应计价规则");
            }
            orderFareDto.setCarModelValuationUuid(carValuationDto.getUuid());
            //额外小费,不是附加服务费
            orderFareDto.setTip(orderParam.getServiceFare());
            //抢单模式
            orderDto.setTypeInteractive(OrderConstant.NEW_ORDER_TYPE_INTERACTIVE_SNATCH);
            //发单
            orderAssignService.addTaxiOrder(orderDto, orderDetailDto, orderFareDto);
            //存入缓存，给重新叫车使用
            orderParam.setOrderUuid(orderDto.getUuid());
            redisCacheService.set(orderDto.getUuid(), orderParam, 10L);
            return ResponseData.buildSuccessResponse("新建订单成功", Boolean.TRUE);
        }
        String orderUuid = saveOrderInfo(orderDto, orderDetailDto, orderFareDto);
        //存入缓存，给重新叫车使用
        orderParam.setOrderUuid(orderUuid);
        redisCacheService.set(orderUuid, orderParam, 10L);
        //执行推单或派单逻辑
        orderAssignService.assignRealTime(orderUuid);
        return ResponseData.buildSuccessResponse("新建订单成功", Boolean.TRUE);
    }


    @Override
    public ResponseData<PageVo<AdminGeneralOrderVo>> queryPageCommon(AdminOrderPageParam orderPageParam) {
        PageBounds pageBounds = new PageBounds(orderPageParam.getPageNum(), orderPageParam.getPageSize());
        PageList<String> pageList = orderMapper.queryPageCommon(MapUtils.convertObjToMap(orderPageParam), pageBounds);
        List<AdminGeneralOrderVo> generalOrderVos = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(pageList)) {
            generalOrderVos = orderMapper.fetchJoinDataByUuid(MapUtils.build("uuids", pageList));
        }
        PageVo<AdminGeneralOrderVo> pageVo = new PageVo(orderPageParam.getPageNum(), orderPageParam.getPageSize(),
                pageList.getPaginator().getTotalCount());
        pageVo.setItems(generalOrderVos);
        return ResponseData.buildSuccessResponse(pageVo);
    }

    @Override
    public ResponseData<List<AdminGeneralOrderVo>> exportCommon(AdminOrderPageParam orderPageParam) {
        return ResponseData.buildSuccessResponse(orderMapper.exportCommon(MapUtils.convertObjToMap(orderPageParam)));
    }

    @Override
    public ResponseData<PageVo<JsonOrderListVo>> orderQueryPage(AdminAssetsPageAdmin assetsPageAdmin) {
        Map<String, Object> map = MapUtils.build(2);
        switch (assetsPageAdmin.getType()) {
            case CommonConstant.PASSENGER:
                map.put("passengerUuid", assetsPageAdmin.getUuid());
                break;
            case CommonConstant.DRIVER:
                map.put("driverUuid", assetsPageAdmin.getUuid());
                break;
            default:
                break;
        }
        PageBounds pageBounds = new PageBounds(assetsPageAdmin.getPageNum(), assetsPageAdmin.getPageSize());
        PageList<JsonOrderListVo> pageList = orderMapper.findOrderList(map, pageBounds);
        PageVo<JsonOrderListVo> pageVo = new PageVo(assetsPageAdmin.getPageNum(), assetsPageAdmin.getPageSize(),
                pageList.getPaginator().getTotalCount());
        pageVo.setItems(pageList);
        return ResponseData.buildSuccessResponse(pageVo);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResponseData<Boolean> close(AdminAssOrCloseParam assOrCloseParam) {
        //设置参数
        String orderUuid = assOrCloseParam.getOrderUuid();
        String closeUser = assOrCloseParam.getUserUuid();
        String closeReason = assOrCloseParam.getReason();
        Date closeTime = new Date();

        OrderDto order = findOrder(orderUuid);
        if (order == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到订单信息");
        }
        //检索订单详情
        OrderDetailDto orderDet = findOrderDetail(orderUuid);
        if (orderDet == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "检索订单详情失败，订单号：" + order.getOrderNo());
        }
        //判断手机订单主状态是否在（1，2，3）不是的话就不允许关闭（4,5支付完成和取消)
        if (order.getMainStatus().equals(OrderConstant.ORDER_MAIN_STATUS_PAYED) || order.getMainStatus().equals(
                OrderConstant.ORDER_MAIN_STATUS_CANCEL.intValue())) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "订单已经支付完成状态或者已经是取消状态，无法关闭订单");
        }
        try {
            //更新订单
            OrderDto updOrder = new OrderDto();
            updOrder.setUuid(order.getUuid());
            updOrder.setSubStatus(OrderConstant.ORDER_STATUS_CLOSE);
            updOrder.setMainStatus(OrderConstant.ORDER_MAIN_STATUS_CANCEL);
            updOrder.setUpdateBy(closeUser);
            orderMapper.edit(updOrder);

            //更新订单详情
            OrderDetailDto updOrderDet = new OrderDetailDto();
            updOrderDet.setUuid(orderDet.getUuid());
            updOrderDet.setCloseReason(closeReason);
            updOrderDet.setCloseUser(closeUser);
            updOrderDet.setCloseTime(closeTime);
            orderDetailMapper.edit(updOrderDet);

            //插入订单生命周期表
            OrderOperateLogDto orderOperateLogDto = new OrderOperateLogDto();
            orderOperateLogDto.setUuid(StringUtils.buildUUID());
            orderOperateLogDto.setOrderUuid(order.getUuid());
            orderOperateLogDto.setAppid(order.getAppid());
            orderOperateLogDto.setType(OrderOperateLogDto.TYPE_CLOSE);
            orderOperateLogDto.setPreMainStatus(order.getMainStatus());
            orderOperateLogDto.setPreSubStatus(order.getSubStatus());
            orderOperateLogDto.setNowMainStatus(OrderConstant.ORDER_MAIN_STATUS_CANCEL);
            orderOperateLogDto.setNowSubStatus(OrderConstant.ORDER_STATUS_CLOSE);
            orderOperateLogDto.setReason(closeReason);
            orderOperateLogDto.setCreateBy(closeUser);
            orderOperateLogDto.setCreateOn(closeTime);
            orderOperateLogMapper.add(orderOperateLogDto);

            //短信消息
            Map<String, Object> map = MapUtils.build();
            map.put("title", "订单关闭");
            map.put("orderUuid", order.getUuid());
            map.put("typeModule", order.getTypeModule());
            String pasContent = "您的订单由于" + closeReason + "由后台关闭。";
            if (CommonConstant.BUSINESS_TYPE_TAXI != order.getTypeModule()) {
                pasContent += "详情可致电：" + driverService.getDriverServiceTel(order.getActualDriverUuid(), null).getData();
            }
            map.put("content", pasContent);
            map.put("report", pasContent);
            //推送给乘客
            PushContent pushContent = PushContent.newInstance4Pas(order.getAppid(), PushContent.ORDER_ADMIN_CLOSE, map);
            pushService.sendMessage(order.getPassengerUuid(), pushContent);
            //推送给司机
            if (OrderConstant.ORDER_MAIN_STATUS_INITIAL.equals(order.getMainStatus()) && OrderConstant.ORDER_STATUS_WAIT.equals(order.getSubStatus())) {
                map.put("content", "订单已由后台关闭");
                map.put("report", "订单已由后台关闭");
            }
            pushContent = PushContent.newInstance4Dri(order.getAppid(), PushContent.ORDER_ADMIN_CLOSE, map);
            pushService.sendMessage(order.getActualDriverUuid(), pushContent);
            // 记录司机状态
            if (StringUtils.isNotEmpty(order.getActualDriverUuid())) {
                DriverDto driverDto = driverService.get(MapUtils.build("uuid", order.getActualDriverUuid())).getData();
                if (null != driverDto) {
                    orderTrackMileageService.statusCycle(driverDto.getAppid(), driverDto.getUuid(), order.getUuid(),
                            driverDto.getCarUuid(), DriverStatusCycleDto.ACTION_CANCEL);
                }
            }
            //通知消息
            InformThreadPoolUtil.execute(new OrderStatusInformThread(order, OrderEvent.CUS_CANCEL));
            //解绑司机
            CompletableFuture.runAsync(() -> orderService.removeDriverLock(order.getActualDriverUuid()));
            //解绑隐私号
            CompletableFuture.runAsync(() -> orderSecretNoService.unbind(order.getUuid()));
            return ResponseData.buildSuccessResponse("关闭订单成功", Boolean.TRUE);
        } catch (Exception e) {
            log.error("关闭订单失败，orderUuid：{}", orderUuid, e);
            return ResponseData.buildSuccessResponse("关闭订单失败", Boolean.FALSE);
        }
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResponseData<Boolean> closeTaxiOrder(AdminAssOrCloseParam assOrCloseParam) {
        //设置参数
        String uuid = assOrCloseParam.getOrderUuid();
        String updater = assOrCloseParam.getUserUuid();
        String reason = assOrCloseParam.getReason();
        //获取订单
        OrderDto orderDto = findOrder(uuid);
        if (orderDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取订单失败");
        }
        //获取订单详情
        OrderDetailDto orderDetailDto = findOrderDetail(uuid);
        if (orderDetailDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取订单详情失败");
        }
        //判断司机订单状态是否正常(行程开始前，才可以改派)
        if (orderDto.getSubStatus().intValue() != OrderConstant.ORDER_STATUS_CONFIRM.intValue()
                && orderDto.getSubStatus().intValue() != OrderConstant.ORDER_STATUS_POOLING_WAIT.intValue()
                && orderDto.getSubStatus().intValue() != OrderConstant.ORDER_STATUS_POOLING_FULL.intValue()
                && orderDto.getSubStatus().intValue() != OrderConstant.ORDER_STATUS_GO.intValue()
                && orderDto.getSubStatus().intValue() != OrderConstant.ORDER_STATUS_ARRIVE.intValue()) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "关闭订单失败，改订单已经支付或者已经关闭");
        }
        try {
            //更新订单信息
            OrderDto updOrderDto = new OrderDto();
            updOrderDto.setUuid(orderDto.getUuid());
            updOrderDto.setMainStatus(new Integer(OrderConstant.ORDER_MAIN_STATUS_CANCEL.intValue()));
            updOrderDto.setSubStatus(OrderConstant.ORDER_STATUS_CLOSE.intValue());
            updOrderDto.setUpdateBy(updater);
            updOrderDto.setUpdateOn(new Date());
            orderMapper.edit(updOrderDto);
            //更新订单详情信息
            OrderDetailDto updOrderDetailDto = new OrderDetailDto();
            updOrderDetailDto.setUuid(orderDetailDto.getUuid());
            updOrderDetailDto.setCloseReason(reason);
            updOrderDetailDto.setUpdateOn(new Date());
            updOrderDetailDto.setUpdateBy(updater);
            orderDetailMapper.edit(updOrderDetailDto);

            Map<String, Object> map = MapUtils.build();
            map.put("title", "关闭订单");
            map.put("content", "关闭订单已经被关闭，请及时查看");
            map.put("report", "您有一个订单已由后台关闭，可进入应用查看详情");
            map.put("orderUuid", orderDto.getUuid());
            map.put("typeModule", orderDto.getTypeModule());
            //推送给司机
            PushContent pushContent = PushContent.newInstance4Dri(orderDto.getAppid(), PushContent.ORDER_ADMIN_CLOSE, map);
            pushService.sendMessage(orderDto.getActualDriverUuid(), pushContent);
            //推送给乘客
            pushContent = PushContent.newInstance4Pas(orderDto.getAppid(), PushContent.ORDER_ADMIN_CLOSE, map);
            pushService.sendMessage(orderDto.getPassengerUuid(), pushContent);
            return ResponseData.buildSuccessResponse(Boolean.TRUE);
        } catch (Exception e) {
            log.error("系统异常，关闭订单失败, orderUuid:{}", assOrCloseParam.getOrderUuid(), e);
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "系统异常，关闭订单失败");
        }
    }

    @Override
    public ResponseData<Boolean> abnormalRemark(AdminOrderAbnormalParam abnormalParam) {
        OrderDetailDto orderDetailDto = new OrderDetailDto();
        orderDetailDto.setOrderUuid(abnormalParam.getOrderUuid());
        if (ABNORMAL_LIST.contains(abnormalParam.getTypeAbnormal()) && abnormalParam.getRefundFare() != null) {
            RefundParam refundParam = new RefundParam();
            refundParam.setOrderUuid(abnormalParam.getOrderUuid());
            refundParam.setRefundFare(abnormalParam.getRefundFare());
            refundParam.setRemark(abnormalParam.getRemark());
            refundParam.setCreateBy(abnormalParam.getUserUuid());
            ResponseData<Integer> refund = refundService.refund(refundParam);
            if (!refund.isSuccess()) {
                return ResponseData.buildErrorResponse(refund.getErrCode(), refund.getMsg());
            }
        }
        orderDetailDto.setTypeAbnormal(abnormalParam.getTypeAbnormal());
        return ResponseData.buildSuccessResponse(orderDetailMapper.updateByOrderUuid(orderDetailDto) > 0);
    }


    @Override
    public ResponseData<PageVo<AdminChildOrderInfoVo>> notAssignJoinOrderPage(AdminJoinRelateParam adminJoinRelateParam) {
        Map<String, Object> build = MapUtils.convertObjToMap(adminJoinRelateParam);
        // 拼车订单状态列表
        List<Integer> joinStatusList = new ArrayList<>();
        if (adminJoinRelateParam.getJoinStatus() == null) {
            joinStatusList.add(OrderConstant.ORDER_JOIN_STATUS_SUBING);
            joinStatusList.add(OrderConstant.ORDER_JOIN_STATUS_SUB_OK);
        } else {
            joinStatusList.add(adminJoinRelateParam.getJoinStatus());
            //在状态tab页 按照时间排序
            build.put("isStatusTab", 1);
        }
        build.put("joinStatus", joinStatusList);
        // 订单模块列表
        List<Integer> typeModuleList = new ArrayList<>();
        if (adminJoinRelateParam.getTypeModule() == null) {
            typeModuleList.add(CommonConstant.BUSINESS_TYPE_POOL);
            typeModuleList.add(CommonConstant.BUSINESS_TYPE_PARCEL);
        } else {
            typeModuleList.add(adminJoinRelateParam.getTypeModule());
        }
        build.put("typeModule", typeModuleList);
        PageBounds pageBounds = new PageBounds(adminJoinRelateParam.getPageNum(), adminJoinRelateParam.getPageSize());
        PageList<AdminChildOrderInfoVo> pageList = orderMapper.notAssignJoinOrderPage(build, pageBounds);
        PageVo<AdminChildOrderInfoVo> pageVo = new PageVo(adminJoinRelateParam.getPageNum(), adminJoinRelateParam
                .getPageSize(), pageList.getPaginator().getTotalCount());
        pageVo.setItems(pageList);
        return ResponseData.buildSuccessResponse(pageVo);
    }

    @Override
    public ResponseData<PageVo<AdminMainOrderInfoVo>> yetAssignJoinOrderPage(AdminJoinRelateParam adminJoinRelateParam) {
        Map<String, Object> paraMap = MapUtils.convertObjToMap(adminJoinRelateParam);
        buildOrderQueryParam(adminJoinRelateParam, paraMap);
        PageBounds pageBounds = new PageBounds(adminJoinRelateParam.getPageNum(), adminJoinRelateParam.getPageSize());
        PageList<AdminMainOrderInfoVo> pageList = orderMapper.yetAssignJoinOrderPage(paraMap, pageBounds);
        if (CollectionUtils.isNotEmpty(pageList)) {
            Set<String> chlidOrderUuidList = new HashSet<>();
            for (AdminMainOrderInfoVo mainOrderInfoVo : pageList) {
                chlidOrderUuidList.addAll(org.springframework.util.StringUtils.commaDelimitedListToSet(mainOrderInfoVo.getOrderUuidStr()));
                mainOrderInfoVo.setOrderUuidStr(null);
            }
            List<AdminChildOrderInfoVo> chlidOrderList = orderMapper.getChildOrderInfoById(MapUtils.build("orderUuidList", chlidOrderUuidList));
            Map<String, List<AdminChildOrderInfoVo>> childOrderMap = chlidOrderList.stream().collect(Collectors
                    .groupingBy(AdminChildOrderInfoVo::getMainOrderUuid));
            for (AdminMainOrderInfoVo mainOrderInfoVo : pageList) {
                mainOrderInfoVo.setChildOrderInfoVoList(childOrderMap.get(mainOrderInfoVo.getMainOrderUuid()));
            }
        }
        PageVo<AdminMainOrderInfoVo> pageVo = new PageVo(adminJoinRelateParam.getPageNum(), adminJoinRelateParam
                .getPageSize(), pageList.getPaginator().getTotalCount());
        pageVo.setItems(pageList);
        return ResponseData.buildSuccessResponse(pageVo);
    }

    /**
     * 导出订单查询
     *
     * @param adminJoinRelateParam
     * @return
     */
    @Override
    public ResponseData<List<AdminMainOrderInfoVo>> exportYetAssignJoinOrder(AdminJoinRelateParam adminJoinRelateParam) {
        Map<String, Object> paraMap = MapUtils.convertObjToMap(adminJoinRelateParam);
        buildOrderQueryParam(adminJoinRelateParam, paraMap);
        List<AdminMainOrderInfoVo> list = orderMapper.exportYetAssignJoinOrder(paraMap);
        if (CollectionUtils.isNotEmpty(list)) {
            Set<String> chlidOrderUuidList = new HashSet<>();
            for (AdminMainOrderInfoVo mainOrderInfoVo : list) {
                chlidOrderUuidList.addAll(org.springframework.util.StringUtils.commaDelimitedListToSet(mainOrderInfoVo.getOrderUuidStr()));
                mainOrderInfoVo.setOrderUuidStr(null);
            }
            List<AdminChildOrderInfoVo> chlidOrderList = orderMapper.getChildOrderInfoById(MapUtils.build("orderUuidList", chlidOrderUuidList));
            Map<String, List<AdminChildOrderInfoVo>> childOrderMap = chlidOrderList.stream().collect(Collectors
                    .groupingBy(AdminChildOrderInfoVo::getMainOrderUuid));
            for (AdminMainOrderInfoVo mainOrderInfoVo : list) {
                mainOrderInfoVo.setChildOrderInfoVoList(childOrderMap.get(mainOrderInfoVo.getMainOrderUuid()));
            }
        }
        return ResponseData.buildSuccessResponse(list);
    }

    /**
     * 构造订单查询参数
     */
    private void buildOrderQueryParam(AdminJoinRelateParam adminJoinRelateParam, Map paraMap) {
        // 拼车订单状态列表
        List<Integer> joinStatusList = new ArrayList<>();
        //是否已关闭
        int closeStatus = adminJoinRelateParam.getCloseStatus() == null ? 0 : adminJoinRelateParam.getCloseStatus();
        if (adminJoinRelateParam.getJoinStatus() == null && closeStatus != OrderConstant.ORDER_CLOSE_STATUS_CLOSED) {
            paraMap.put("closeStatus", null);
        } else {
            paraMap.put("closeStatus", closeStatus);
        }

        //是否审核退款
        int auditRefund = adminJoinRelateParam.getAuditRefund() == null ? 0 : adminJoinRelateParam.getAuditRefund();
        if (adminJoinRelateParam.getJoinStatus() != null && auditRefund != 1 && closeStatus != 1) {
            switch (adminJoinRelateParam.getJoinStatus()) {
                //待出发包含400 410 420 430
                case OrderConstant.ORDER_JOIN_STATUS_WAIT_START:
                    joinStatusList.add(OrderConstant.ORDER_JOIN_STATUS_WAIT_START);
                    joinStatusList.add(OrderConstant.ORDER_JOIN_STATUS_DRIVER_DEPARTURE);
                    joinStatusList.add(OrderConstant.ORDER_JOIN_STATUS_ARRIVE_POINT);
                    joinStatusList.add(OrderConstant.ORDER_JOIN_STATUS_PASSENGER_ABOARD);
                    break;
                //行程中包含500 510
                case OrderConstant.ORDER_JOIN_STATUS_STARTED:
                    joinStatusList.add(OrderConstant.ORDER_JOIN_STATUS_STARTED);
                    joinStatusList.add(OrderConstant.ORDER_JOIN_STATUS_CONFIRM_FARE);
                    break;
                //已完成包含 520 530 600 700
                case OrderConstant.ORDER_JOIN_STATUS_COMPLETED:
                    joinStatusList.add(OrderConstant.ORDER_JOIN_STATUS_PASSENGER_PAY);
                    joinStatusList.add(OrderConstant.ORDER_JOIN_STATUS_DRIVER_PAY);
                    joinStatusList.add(OrderConstant.ORDER_JOIN_STATUS_COMPLETED);
                    joinStatusList.add(OrderConstant.ORDER_JOIN_STATUS_COMPLETED);
                    break;
                default:
                    joinStatusList.add(adminJoinRelateParam.getJoinStatus());
                    break;
            }
        }
        if (auditRefund == 1) {
            paraMap.put("closeStatus", 1);
        }
        paraMap.put("joinStatus", joinStatusList);
        // 拼车订单模块列表
        List<Integer> typeModuleList = new ArrayList<>();
        if (adminJoinRelateParam.getTypeModule() == null) {
            typeModuleList.add(CommonConstant.BUSINESS_TYPE_POOL);
            typeModuleList.add(CommonConstant.BUSINESS_TYPE_PARCEL);
        } else {
            typeModuleList.add(adminJoinRelateParam.getTypeModule());
        }
        paraMap.put("typeModule", typeModuleList);
    }

    @Override
    public ResponseData<PageVo<JoinOrderAssignVo>> queryByAssign(AdminCrosstownAssignQueryParam queryParam) {
        PageBounds pageBounds = new PageBounds(queryParam.getPageNum(), queryParam.getPageSize());
        Map<String, Object> params = MapUtils.convertObjToMap(queryParam);
        List<JoinOrderAssignVo> orderList = orderMapper.queryByAssign(params, pageBounds);

        //获取订单详情
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("orderUuid", params.get("orderUuid"));
        List<OrderDetailDto> list = orderDetailMapper.list(paramMap);
        if (CollectionUtils.isEmpty(list)) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取订单详情失败");
        }
        OrderDetailDto orderDetailDto = list.get(0);
        paramMap.clear();
        paramMap.put("districtUuid", orderDetailDto.getOriginCityUuid());
        paramMap.put("businessType", CommonConstant.BUSINESS_TYPE_POOL);
        SysAssignConfigDto sysAssignConfigDto = sysAssignConfigService.get(paramMap).getData();
        if (sysAssignConfigDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取跨城派单规则失败");
        }
        //非合并派单时 计算权重分
        if (!queryParam.isMergeAssign()) {
            for (JoinOrderAssignVo joinOrderAssignVo : orderList) {
                Double weightScore = crosstownOrderProcessor.calWeightScore(sysAssignConfigDto, orderDetailDto, joinOrderAssignVo.getResNum(), joinOrderAssignVo.getAllPassengerOrderInfoList());
                joinOrderAssignVo.setWeightScore(weightScore);
            }
            //按照权重得分降序
            Collections.sort(orderList, (a, b) -> b.getWeightScore().compareTo(a.getWeightScore()));
        }
        //因权重分无法数据库计算 得出分数后 进行手动分页
        PageList<JoinOrderAssignVo> resultPageList = new PageList();
        for (int i = 0; i < orderList.size(); i++) {
            if (i >= (queryParam.getPageNum()) * queryParam.getPageSize()) {
                break;
            }
            if (i >= (queryParam.getPageNum() - 1) * queryParam.getPageSize()) {
                resultPageList.add(orderList.get(i));
            }
        }
        PageVo<JoinOrderAssignVo> pageVo = new PageVo(queryParam.getPageNum(), queryParam.getPageSize(),
                orderList.size());
        pageVo.setItems(resultPageList);
        return ResponseData.buildSuccessResponse(pageVo);
    }

    @Override
    public ResponseData<AdminJoinCountVo> countJoinOrder(AdminParam adminParam) {
        return ResponseData.buildSuccessResponse(orderMapper.countJoinOrder(adminParam));
    }

    @Override
    public ResponseData<PageVo<JoinOrderAssignVo>> mergeAssignOrderQuery(AdminMergeOrderPageParam mergeOrderPageParam) {
        PageBounds pageBounds = new PageBounds(mergeOrderPageParam.getPageNum(), mergeOrderPageParam.getPageSize());
        Map<String, Object> objectMap = MapUtils.convertObjToMap(mergeOrderPageParam);
        PageList<JoinOrderAssignVo> pageList = orderMapper.mergeAssignOrderQuery(objectMap, pageBounds);
        PageVo<JoinOrderAssignVo> pageVo = new PageVo(mergeOrderPageParam.getPageNum(), mergeOrderPageParam
                .getPageSize(), pageList.getPaginator().getTotalCount());
        pageVo.setItems(pageList);
        return ResponseData.buildSuccessResponse(pageVo);
    }

    @Override
    public ResponseData<PageVo<AdminOrderInvoiceDetailVo>> orderInvoicePage(AdminOrderInvoicePageParam orderInvoicePageParam) {
        PageBounds pageBounds = new PageBounds(orderInvoicePageParam.getPageNum(), orderInvoicePageParam.getPageSize());
        Set<String> orderIds = org.springframework.util.StringUtils.commaDelimitedListToSet(orderInvoicePageParam.getOrderUuids());
        PageList<AdminOrderInvoiceDetailVo> pageList = orderMapper.orderInvoicePage(orderIds, pageBounds);
        PageVo<AdminOrderInvoiceDetailVo> pageVo = new PageVo(orderInvoicePageParam.getPageNum(), orderInvoicePageParam.getPageSize(),
                pageList.getPaginator().getTotalCount());
        pageVo.setItems(pageList);
        return ResponseData.buildSuccessResponse(pageVo);
    }

    @Override
    public ResponseData<PageVo<AdminMapTodayOrderVo>> orderTodayList(AdminMapTodayOrderPageParam todayOrderParam) {
        PageBounds pageBounds = new PageBounds(todayOrderParam.getPageNum(), todayOrderParam.getPageSize());
        PageList<AdminMapTodayOrderVo> pageList = orderMapper.orderTodayList(todayOrderParam, pageBounds);
        PageVo<AdminMapTodayOrderVo> pageVo = new PageVo(todayOrderParam.getPageNum(), todayOrderParam.getPageSize(),
                pageList.getPaginator().getTotalCount());
        pageVo.setItems(pageList);
        return ResponseData.buildSuccessResponse(pageVo);
    }


    @Override
    public ResponseData<AdminMapTodayOrderVo> mapOrderDetail(String orderUuid) {
        return ResponseData.buildSuccessResponse(orderMapper.orderTodayList(orderUuid));
    }

    /**
     * 主单详情
     *
     * @param mainOrderUuid
     * @return
     */
    @Override
    public ResponseData<Map<String, Object>> mainOrderDetail(String mainOrderUuid) {
        AdminMainOrderDetailVo mainOrderDetailVo = orderMapper.mainOrderDetail(mainOrderUuid);
        List<AdminOrderTravelStatusVO> travelList = orderMapper.orderTravelStatus(mainOrderUuid);
        //取出乘客名称
        Map<String, String> passengerMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(travelList)) {
            for (AdminOrderTravelStatusVO adminOrderTravelStatusVO : travelList) {
                passengerMap.put(adminOrderTravelStatusVO.getOrderUuid(), adminOrderTravelStatusVO.getPassengerName());
            }
        }
        List<DriverLocation> driverLocationList = locationService.findMainOrderLocation(mainOrderUuid).getData();
        List<OrderLocationVo> locationList = new ArrayList<>();
        List<AdminOrderStatusPointVO> statusPointList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(driverLocationList)) {
            Map<String, String> pointMap = getPointMap();
            for (DriverLocation driverLocation : driverLocationList) {
                Coordinate coordinate = driverLocation.getCoordinate();
                OrderLocationVo orderLocationVo = new OrderLocationVo();
                orderLocationVo.setLat(coordinate.getLat());
                orderLocationVo.setLng(coordinate.getLng());
                locationList.add(orderLocationVo);

                if (pointMap.containsKey(driverLocation.getPositionType())) {
                    AdminOrderStatusPointVO orderStatusPointVO = new AdminOrderStatusPointVO();
                    orderStatusPointVO.setLat(coordinate.getLat());
                    orderStatusPointVO.setLng(coordinate.getLng());
                    orderStatusPointVO.setOrderUuid(driverLocation.getOrderUuid());
                    orderStatusPointVO.setPositionType(driverLocation.getPositionType());
                    orderStatusPointVO.setUploadTime(driverLocation.getUploadTime());
                    orderStatusPointVO.setPassengerName(passengerMap.get(driverLocation.getOrderUuid()));
                    statusPointList.add(orderStatusPointVO);
                }
            }
        }
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("orderDetail", mainOrderDetailVo);
        resultMap.put("travelStatusList", travelList);
        resultMap.put("locationList", locationList);
        resultMap.put("statusPointList", statusPointList);

        return ResponseData.buildSuccessResponse(resultMap);
    }

    /**
     * 位置点类型
     *
     * @return
     */
    private Map<String, String> getPointMap() {
        Map<String, String> pointMap = new HashMap<>();
        pointMap.put("CKSC", "CKSC");
        pointMap.put("SJCF", "SJCF");
        pointMap.put("CKXC", "CKXC");
        return pointMap;
    }


    /**
     * 跨城重新派单
     *
     * @param orderUuid 订单 uuid
     * @return
     */
    @Override
    public ResponseData<Boolean> reAssign(String orderUuid) {
        OrderDto orderDto = orderMapper.list(MapUtils.build("uuid", orderUuid)).get(0);
        if (null == orderDto) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "未找到订单信息");
        }
        if (orderDto.getCloseStatus() == OrderConstant.ORDER_CLOSE_STATUS_CLOSED) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "订单已被取消，请刷新");
        }
        if (orderDto.getJoinStatus() > OrderConstant.ORDER_JOIN_STATUS_WAIT_START) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "订单已开始行程，请刷新");
        }
        if (orderDto.getJoinStatus() < OrderConstant.ORDER_JOIN_STATUS_WAIT_START) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "订单非待出发状态，无法操作，请刷新");
        }
        String mainOrderUuid = orderDto.getMainOrderUuid();
        //关闭订单与司机操作订单互斥
        if (StringUtils.isNotEmpty(mainOrderUuid)) {
            ResponseData lockRsd = crosstownOrderProcessor.handleLock(mainOrderUuid);
            //司机正在操作订单
            if (!lockRsd.isSuccess()) {
                return lockRsd;
            }
        }

        OrderDetailDto mainOrderDetail = orderDetailMapper.list(MapUtils.build("orderUuid", orderDto.getMainOrderUuid())).get(0);
        int reBindCount = orderMapper.reBindMainOrder(orderUuid);
        if (reBindCount != 1) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "操作失败，请稍后重试");
        }
        //是否存在子单
        int existsChildOrder = orderMapper.existChildOrder(orderDto.getMainOrderUuid());
        if (existsChildOrder == 0) {
            orderMapper.closeMainOrder(orderDto.getMainOrderUuid());
        } else {
            //更新主单信息
            OrderDetailDto updMainOrderDetail = new OrderDetailDto();
            updMainOrderDetail.setUuid(mainOrderDetail.getUuid());
            if (orderDto.getTypeModule() == CommonConstant.BUSINESS_TYPE_PARCEL) {
                updMainOrderDetail.setParcelOrderNum(mainOrderDetail.getParcelOrderNum() - 1);
            } else {
                OrderDto mainOrderDto = orderMapper.list(MapUtils.build("uuid", orderDto.getMainOrderUuid())).get(0);
                OrderDto updMainOrder = new OrderDto();
                OrderDetailDto orderDetail = orderDetailMapper.list(MapUtils.build("orderUuid", orderDto.getUuid())).get(0);
                updMainOrder.setSeatNum(mainOrderDto.getSeatNum() - orderDto.getSeatNum());
                updMainOrder.setUuid(mainOrderDto.getUuid());
                updMainOrderDetail.setActualPasNum(mainOrderDetail.getActualPasNum() - orderDetail.getActualPasNum());
                updMainOrderDetail.setAdultNum(mainOrderDetail.getAdultNum() - orderDetail.getAdultNum());
                updMainOrderDetail.setResNum(mainOrderDetail.getResNum() + orderDto.getSeatNum());
                orderMapper.edit(updMainOrder);
            }
            orderDetailMapper.edit(updMainOrderDetail);
        }

        return ResponseData.buildSuccessResponse(true);
    }
}
